<template>
  <div
    id="k-linebox"
    class="sTradingviewContent"
    :class="isFullscreen ? 'h-100' : 'h-94'"
    v-loading="loading"
    :element-loading-background="
      themeType === 'night' ? 'rgba(0, 0, 0, 0.6)' : 'rgba(255, 255, 255, 0.6)'
    "
  >
    <div>
      <div class="top parent">
        <ul class="time-box text-14 quote-key-text lh-20 flex pd-lf-base">
          <li
            class="item"
            v-for="(item, index) in timeArr"
            :class="item.time === time ? 'quote-value-text item-border' : ''"
            :key="index"
            @click="selectTime(item.time, item.type)"
          >
            {{ getName(item.time) }}
          </li>
        </ul>
        <div class="btn-box">
          <!-- <span class="btn-txt">指标</span> -->
          <i
            @click="actionById('insertIndicator')"
            class="iconfont text-16 quote-key-text mg-rt-md iconzhibiao point"
          ></i>
          <i
            @click="actionById('scalesProperties')"
            class="iconfont text-16 quote-key-text mg-rt-md iconshezhi1 point"
          ></i>
          <i
            @click="fullscreen"
            class="iconfont text-16 quote-key-text mg-rt-xs point"
            :class="isFullscreen ? 'icontuichuquanping' : 'iconquanping'"
          ></i>
        </div>
      </div>
    </div>
    <div :id="domId" class="sTradingviewView"></div>
    <!-- <Loading :show="loading" /> -->
  </div>
</template>
<script>
import {  widget  } from "./static/charting_library.min.js";
import datafeeds from "./static/datafees.js";
import config from "./config";
import tabsConfig from "./config/tabs";
import { Tab, Tabs } from "vant";
import { quotationseo } from "@/api/currency";
import jstz from "jstz";
const timezone = jstz.determine();
const timezoneName = timezone.name();

export default {
  name: "stockSTradingview",
  props: {
    //Dom元素id
    domId: {
      type: String,
      default: function() {
        return "tradeView";
      },
    },
    // 小数值
    decimal: {
      type: [String, Number],
      default: function() {
        return 100;
      },
    },
    //是否显示MACD
    is_MACD: {
      type: Boolean,
      default: function() {
        return false;
      },
    },
    klineData: Object,
    pageType: Number, // 1币币交易 2合约交易 3秒合约交易
  },
  components: {
    [Tab.name]: Tab,
    [Tabs.name]: Tabs,
  },
  data() {
    return {
      loading: false,
      tabsArr: tabsConfig,
      symbol: null, //币名称
      interval: "1", //默认显示规则
      chart: null,
      moreTxt: null,
      mainTime: ["1min", "15min", "60min", "1day"],
      timeList: ["5min", "30min", "240min", "1week", "1month"],
      timeArr: [
        { time: "1min", type: 1 },
        { time: "5min", type: 2 },
        { time: "15min", type: 1 },
        { time: "30min", type: 2 },
        { time: "60min", type: 1 },
        { time: "240min", type: 2 },
        { time: "1day", type: 1 },
        { time: "1week", type: 2 },
        { time: "1month", type: 2 },
      ],
      isMore: false,
      initdata: {},
      countDate: 0, //累加条数
      startData: 0, //起始条数
      lengsData: 200, //结束长度
      datafeeds: new datafeeds(this),
      onLoadedCallback: null, //初始数据回调
      onRealtimeCallback: null, //websocket数据回调
      time: "1min",
      chartData: [],
      lastTime: 0,
      nextTime: 0,
      isFullscreen: false,
      fullscreenStyle: {},
      params: {
        currency_match_id: null,
        page: 0,
        limit: 500,
        time_type: null,
      },
      addStudiesTimer: null,
    };
  },
  computed: {
    themeType() {
      return this.$store.state.exchange.theme;
    },
    tradeType() {
      return this.$store.state.exchange.tradeType;
    },
    changeData() {
      // console.log("测试deal");
      return this.pageType === 1
        ? this.$store.state.exchange.deal_data
        : this.pageType === 2
        ? this.$store.state.exchange.lever_data
        : this.$store.state.exchange.second_data;
    },
    theme() {
      return this.$store.state.user.theme;
    },
    klineResolution() {
      return this.$store.state.exchange.klineResolution;
    },
    local() {
      if (this.$store.state.user.local === "tc") {
        return "zh_TW";
      } else if (
        this.$store.state.user.local === "id" ||
        this.$store.state.user.local === "fi"
      ) {
        return "en";
      } else if (this.$store.state.user.local === "vn") {
        return "vi";
      } else {
        return this.$store.state.user.local;
      }
    },
    klStudies() {
      return this.$store.state.user.klStudies;
    },
  },
  watch: {
    themeType: {
      handler(val) {
        console.log(val);
        this.params.page = 0;
        this.chartData = [];
        // this.removeChart();
        this.initChart();
      },
    },
    changeData: {
      // handler() {
      //   this.params.page = 0;
      //   this.symbol =
      //     this.changeData.currency_name + "_" + this.changeData.legal_name;
      //   this.chart.activeChart().setChartType(1);
      //   // this.onResetCacheNeededCallback();
      //   this.setSymbols();
      //   this.chart.activeChart().resetData();
      // },
      handler(val, oldVal) {
        if (val.id !== oldVal.id) {
          // this.params.page = 0;
          // this.symbol =
          //   this.changeData.currency_name + "_" + this.changeData.legal_name;
          // this.chart.activeChart().setChartType(1);
          // // this.onResetCacheNeededCallback();
          // this.setSymbols();
          // this.chart.activeChart().resetData();
          console.log(val, oldVal);
          this.params.page = 0;
          this.chartData = [];
          this.removeChart();
          this.initChart();
        }
      },
      deep: true, //true 深度监听
    },
    klineData: {
      handler(val) {
        // eslint-disable-next-line no-unused-vars
        const newData = this.getNewData(val);
        if (newData && this.lastTime) {
          const timestamp = this.calcUpdateTime(newData.time);
          const datav = {
            open: Number(newData.open),
            close: Number(newData.close),
            low: Number(newData.low),
            high: Number(newData.high),
            volume: Number(newData.volume),
            timestamp: Number(timestamp),
            time: Number(timestamp),
          };
          // console.log("timestamp", this.lastTime <= Number(timestamp));
          //  新数据的时间比最后一条数据的时间大才更新图表
          if (this.lastTime <= Number(timestamp)) {
            if (this.onRealtimeCallback) {
              this.onRealtimeCallback(datav);
            }
          }
        }
      },
      deep: true,
    },
  },
  mounted() {
    //加载K线图
    this.initChart();
    let self = this;
    window.onresize = function() {
      if (!self.checkFull()) {
        // 要执行的动作
        self.isFullscreen = !self.isFullscreen;
      }
    };
    document.addEventListener("stradingvisibilitychange", this.visibilityFn);
  },
  //销毁之前
  beforeUnmount() {
    let that = this;
    if (that.chart) {
      that.saveStudies();
      that.removeChart();
    }
    window.onresize = "";
    clearTimeout(that.addStudiesTimer);
    document.removeEventListener("stradingvisibilitychange", this.visibilityFn);
  },
  methods: {
    visibilityFn() {
      // 用户息屏、或者切到后台运行 （离开页面）
      if (document.visibilityState === "hidden") {
        if (self.chart) {
          self.saveStudies();
          self.removeChart();
        }
        window.onresize = "";
        clearTimeout(self.addStudiesTimer);
      }
      // 用户打开或回到页面
      if (document.visibilityState === "visible") {
        self.params.page = 0;
        self.chartData = [];
        self.initChart();
        window.onresize = function() {
          if (!self.checkFull()) {
            // 要执行的动作
            self.isFullscreen = !self.isFullscreen;
          }
        };
      }
    },
    checkFull() {
      //判断是否全屏
      return (
        document.fullscreenElement ||
        document.msFullscreenElement ||
        document.mozFullScreenElement ||
        document.webkitFullscreenElement ||
        false
      );
    },
    initChart() {
      //加载K线图
      this.symbol =
        this.changeData.currency_name + "_" + this.changeData.legal_name;
      this.time = this.klineResolution.time;
      this.interval = this.klineResolution.interval;
      if (this.timeType === 2) {
        this.moreTxt = this.getName(this.time);
      } else {
        this.moreTxt = null;
      }
      this.loadChart();
    },
    /**
     * 切换触发
     * e {string} reset=重置数据
     */
    changeTabs(e) {
      // let self = this;
      this.interval = e;
      let chartType = e == "1s" ? 3 : 1;
      this.chart.activeChart().setChartType(chartType);
      this.setSymbols();
      this.chart.activeChart().resetData();
      // this.webSocket("load");
      //MA显示隐藏
      this.toggleStudies(e);
    },

    //过滤 时段
    filter(time) {
      return time == "1s" ? "1S" : time;
    },

    // 请求数据
    getBars(
      symbolInfo,
      resolution,
      rangeStartDate,
      rangeEndDate,
      onHistoryCallback,
      onLoadedCallback
    ) {
      this.onLoadedCallback = onLoadedCallback;
      this.onHistoryCallback = onHistoryCallback;
      this.getChartData(this.onHistoryCallback);
    },
    /**
     * 获取图表数据
     */
    getChartData(onHistoryCallback) {
      // const end_time = +new Date();
      // const start_time = end_time - getTime();
      this.loading = true;
      this.params.currency_match_id = this.changeData.id;
      this.params.time_type = this.time;
      if (this.params.time_type === "60min") {
        this.params.time_type = "1hour";
      }
      if (this.params.time_type === "240min") {
        this.params.time_type = "4hour";
      }
      quotationseo(this.params)
        .then((res) => {
          this.params.page++;
          const data = res.data.items;
          this.chartData = data.map((item) => {
            item.timestamp = item.time;
            return item;
          });
          if (this.chartData?.length) {
            onHistoryCallback(this.chartData, {
              noData: false,
            });
            this.lastTime = this.chartData[this.chartData?.length - 1]?.time;
            this.nextTime = this.lastTime + this.getTime() * 60000;
            if (this.chartData?.length <= 20) {
              this.initdata.to = this.lastTime / 1000;
              this.initdata.from = this.chartData[0].time / 1000;
            } else {
              this.initdata.to = this.lastTime / 1000;
              this.initdata.from = this.initdata.to - this.getTime() * 60;
            }
          } else {
            onHistoryCallback([], { noData: true });
          }
          this.loading = false;
        })
        .finally(() => {
          this.loading = false;
        });
    },
    getTime() {
      let time = 0;
      if (this.time.includes("min")) {
        time = Number(this.time.split("min")[0]);
      } else if (this.time.includes("day")) {
        time = 24 * 60;
      } else if (this.time.includes("week")) {
        time = 24 * 60 * 7;
      } else if (this.time.includes("month")) {
        time = 24 * 60 * 31;
      } else if (this.time.includes("year")) {
        time = 12 * 24 * 60 * 30;
      }
      return time;
    },
    getNewData(data) {
      switch (this.time) {
        case "1min":
          return data.oneMinute;
        case "5min":
          return data.fiveMinute;
        case "15min":
          return data.fifteenMinute;
        case "30min":
          return data.thirtyMinute;
        case "60min":
          return data.oneHour;
        case "240min":
          return data.fourHour;
        case "1day":
          return data.oneDay;
        case "1week":
          return data.oneWeek;
        case "1month":
          return data.oneMonth;
        case "1year":
          return data.oneYear;
      }
    },
    /**
     * 获取更新时间
     * @param timestamp
     */
    calcUpdateTime(timestamp) {
      // 新数据时间点 < 最后一条时间点 不更新图表(数据会乱掉)
      if (this.lastTime > timestamp) {
        return timestamp;
      }
      // 新数据时间在最后一个时间点跟下个时间点中间 则更新最后一条的时间
      if (this.lastTime <= timestamp && this.nextTime > timestamp) {
        return this.lastTime;
      } else if (this.nextTime <= timestamp) {
        // 新数据时间大于下一个时间点 则图表更新下一个时间点
        this.lastTime = this.nextTime;
        this.nextTime = this.lastTime + this.getTime() * 60000;
      }
      return timestamp;
    },
    //socket
    subscribeBars(
      symbolInfo,
      resolution,
      onRealtimeCallback,
      subscriberUID,
      onResetCacheNeededCallback
    ) {
      this.onRealtimeCallback = onRealtimeCallback;
      this.onResetCacheNeededCallback = onResetCacheNeededCallback;
      // this.webSocket("get");
    },

    //获取配置信息
    getSymbol(symbol) {
      return {
        name: symbol,
        full_name: symbol,
        timezone: timezoneName || "America/New_York", //默认时区
        minmov: 1,
        minmov2: 0,
        pointvalue: 1,
        fractional: false,
        //设置周期 等于所有时间都是交易时段
        session: "24x7",
        has_intraday: true, //布尔值显示商品是否具有日内（分钟）历史数据
        has_no_volume: false,
        //设置是否支持周月线
        has_daily: true,
        //设置是否支持周月线
        has_weekly_and_monthly: true,
        description: symbol,
        //设置精度  100表示保留两位小数   1000三位   10000四位
        pricescale: parseInt(this.decimal),
        ticker: symbol,
        supported_resolutions: [
          "1",
          "5",
          "15",
          "30",
          "60",
          "240",
          "1D",
          "1W",
          "1M",
          "12M",
        ],
        // seconds_multipliers: ["1S", "5S", "15S"],
        // volume_precision: 0, //整数显示此商品的成交量数字的小数位。0表示只显示整数。1表示保留小数位的1个数字字符
        // data_status: "streaming", //数据状态(streaming(实时),endofday(已收盘),pulsed(脉冲),delayed_streaming(延迟流动中))
      };
    },

    //设置品信息(重新获取初始数据/推送数据)
    setSymbols() {
      let self = this;
      self.chart.setSymbol(self.symbol, self.filter(self.interval), function() {
        // self.chart.chart().setVisibleRange(self.initdata);
        self.chart.chart().executeActionById("timeScaleReset");
      });

      this.chart
        .chart()
        .setResolution(
          self.filter(self.interval),
          function onReadyCallback() {}
        );
    },

    //卸载K线
    removeChart() {
      if (this.chart && this.chart._ready) {
        this.chart.remove();
        this.chart = null;
      }
    },

    //加载K线图插件
    loadChart() {
      let self = this;
      // this.webSocket("load");
      let color_bg = "";
      if (this.themeType === "night") {
        color_bg = "#141414";
      } else {
        color_bg = "#20334d";
      }
      config.overrides["paneProperties.background"] = color_bg;
      this.chart = new widget({
        container_id: self.domId, //`id`属性为指定要包含widget的DOM元素id。
        symbol: self.symbol,
        interval: self.filter(self.interval),
        locale: this.local, //  语言
        autosize: true,
        fullscreen: false, //是否占用视图所有空间
        // preset: "mobile",
        toolbar_bg: color_bg, //背景色
        datafeed: this.datafeeds,
        timezone: timezoneName || "America/New_York", //默认时区
        library_path: "/static/charting_library/", //默认脚本核心文件存储位置
        indicators_file_name: "custom-study(MACD红绿).js",
        drawings_access: {
          type: "black",
          tools: [{ name: "Regression Trend" }],
        },
        theme: "Dark",
        //配置项
        ...config,
      });
      this.chart.onChartReady(function() {
        //检查是否存在MA
        self.toggleStudies(self.interval);
        self.subscribeSaveNeeded();
      });
    },
    /**
     * 根据状态 显示隐藏 MA
     * e {string} 时段
     */
    toggleStudies(e) {
      let self = this;
      if (e == "1s") {
        self.chart
          .activeChart()
          ?.getAllStudies()
          .forEach((e) => {
            if (e.name == "Moving Average") {
              self.chart.activeChart().removeEntity(e.id);
            }
          });
      } else {
        //检查是否存在MA
        this.getAllStudiesFun();
      }
    },
    //检查是否有 指标MA
    getAllStudiesFun() {
      let self = this;
      let strArr = [];
      self.chart
        .activeChart()
        ?.getAllStudies()
        .forEach((e) => {
          strArr.push(e.name);
        });
      if (JSON.stringify(strArr).indexOf("Moving Average") == -1) {
        //创建指标
        self.createStudyFun();
      }
    },
    //创建显示指标
    createStudyFun() {
      let self = this;
      //设置均线种类 均线样式
      // self.chart.chart().createStudy('Moving Average', false, false, [5], null, {'Plot.color': 'rgb(150, 95, 196)'});
      // self.chart.chart().createStudy('Moving Average', false, false, [10], null, {'Plot.color': 'rgb(116,149,187)'});
      // self.chart.chart().createStudy('Moving Average', false, false, [20],null,{"plot.color": "rgb(58,113,74)"});
      // self.chart.chart().createStudy('Moving Average', false, false, [30],null,{"plot.color": "rgb(118,32,99)"});
      try {
        self.chart.chart().createStudy("Moving Average", !1, !1, [7], null, {
          "Plot.color": "rgb(150, 95, 196)",
          "Plot.linewidth": 3,
        });
        self.chart.chart().createStudy("Moving Average", !1, !1, [10], null, {
          "Plot.color": "rgb(116,149,187)",
          "Plot.linewidth": 3,
        });
        self.chart.chart().createStudy("Moving Average", !1, !1, [30], null, {
          "plot.color": "rgb(58,113,74)",
          "Plot.linewidth": 3,
        });
        if (self.is_MACD) {
          //self.chart.chart().createStudy("MACD", !1, !1, [20], null, {}); //MACD
          let str = self.$t("assets.average") + "(MACD_Custom)";
          self.chart.chart().createStudy(str, false, false, [20], null, {
            precision: Math.log10(this.decimal),
          }); //自定义MACD
        }
        self.klStudies?.map((val) => {
          if (val.name !== "Moving Average" && val.name !== "Volume") {
            this.chart.chart().createStudy(val.name, false, false);
          }
        });
      } catch (e) {
        console.log(e);
      }
    },
    /**
     * 选择时间
     * @param data 时间
     */
    selectTime(time, type) {
      if (this.time === time) {
        return;
      }
      if (type === 2) {
        this.moreTxt = this.getName(time);
      } else {
        this.moreTxt = null;
      }
      this.time = time;
      this.interval = this.getTimeV(time);
      const params = {};
      params.time = this.time;
      params.interval = this.interval;
      params.timeType = this.type;
      this.$store.dispatch("exchange/changeKlineResolution", params);
      this.params.page = 0;
      this.chart.activeChart().setChartType(1);
      // this.onResetCacheNeededCallback();
      this.setSymbols();
      this.chart.activeChart().resetData();
    },
    /**
     * 全屏/退出全屏
     */
    fullscreen() {
      this.isFullscreen = !this.isFullscreen;
      this.toFullscreen(this.isFullscreen);
      // if (this.isFullscreen) {
      //   const width = document.documentElement.clientWidth;
      //   const height = document.documentElement.clientHeight;
      //   this.fullscreenStyle = {
      //     width: height + "px",
      //     height: width + "px",
      //     top: (height - width) / 2 + "px",
      //     left: 0 - (height - width) / 2 + "px"
      //   };
      // } else {
      //   this.fullscreenStyle = {};
      // }
      // setTimeout(() => {
      //   this.chart?.resize();
      // }, 800);
    },
    toFullscreen(val) {
      let elem = document.getElementById("k-linebox");
      if (val) {
        if (elem.webkitRequestFullScreen) {
          elem.webkitRequestFullScreen();
        } else if (elem.mozRequestFullScreen) {
          elem.mozRequestFullScreen();
        } else if (elem.requestFullScreen) {
          elem.requestFullscreen();
        } else {
          //浏览器不支持全屏API或已被禁用
        }
      } else {
        if (document.exitFullscreen) {
          document.exitFullscreen();
        } else if (document.webkitCancelFullScreen) {
          document.webkitCancelFullScreen();
        } else if (document.mozCancelFullScreen) {
          document.mozCancelFullScreen();
        } else if (document.msExitFullscreen) {
          document.msExitFullscreen();
        }
      }
    },
    /**
     * ID触发图表事件
     * scalesProperties 尺度属性
     * insertIndicator 指标
     */
    actionById(id) {
      let self = this;
      self.chart.activeChart().executeActionById(id);
      if (id == "insertIndicator") {
        console.log(self.domId);
        var box = document.querySelectorAll("[id*=tradingview_]");
        self.$nextTick(() => {
          if (
            box[0].contentWindow.document.getElementsByClassName("tv-dialog")
              .length > 0
          ) {
            let tags = box[0].contentWindow.document.querySelectorAll(
              "[title='指数平滑异同移动平均线(MACD_Custom)']"
            );
            if (tags[0]) {
              tags[0].innerHTML = self.$t("assets.average") + "(MACD_Custom)";
            }
            console.log(tags);
          }
        });
      }
    },
    getName(data) {
      switch (data) {
        case "1min":
          return "1" + this.$t("global.minute");
        case "5min":
          return "5" + this.$t("global.minute");
        case "15min":
          return "15" + this.$t("global.minute");
        case "30min":
          return "30" + this.$t("global.minute");
        case "60min":
          return "1" + this.$t("global.hour");
        case "240min":
          return "4" + this.$t("global.hour");
        case "1day":
          return "1" + this.$t("global.dayLine");
        case "1week":
          return "1" + this.$t("global.weekLine");
        case "1month":
          return "1" + this.$t("global.monthLine");
        case "1year":
          return "1" + this.$t("global.yearLine");
      }
    },
    trogleShow() {
      this.isMore = !this.isMore;
    },
    getTimeV(time) {
      switch (time) {
        case "1min":
          return "1";
        case "5min":
          return "5";
        case "15min":
          return "15";
        case "30min":
          return "30";
        case "60min":
          return "60";
        case "240min":
          return "240";
        case "1day":
          return "1D";
        case "1week":
          return "1W";
        case "1month":
          return "1M";
        case "1year":
          return "12M";
      }
    },
    // 保存指标数据
    saveStudies() {
      const studies = this.chart?.activeChart()?.getAllStudies();
      this.$store.commit("user/SET_KLSTUDIES", studies);
    },
    //图表修改订阅(指标)
    subscribeSaveNeeded() {
      let self = this;
      self.chart.subscribe("onAutoSaveNeeded", () => {
        self.addStudiesTimer = setTimeout(() => {
          self.saveStudies();
          clearTimeout(self.addStudiesTimer);
        }, 2000);
      });
    },
  },
};
</script>
<style lang="less" scoped>
.h-100 {
  height: 100%;
}
.h-94 {
  height: 94.5%;
}
.sTradingviewContent {
  width: 99.5%;
  box-sizing: border-box;
  background: #20334d;
  border-radius: 8px;
  margin-bottom: 30px;
  z-index: 100;
  &.fullscreen-wrap {
    position: fixed;
    width: 100%;
    top: 0;
    left: 0;
    padding-bottom: 50px;
  }
  .top {
    padding: 10px 5px 0;
    display: flex;
    justify-content: space-between;
  }
  .time-box {
    width: 70%;
    .item {
      margin-inline-end: 15px;
      cursor: pointer;
    }
  }
  .btn-box {
    height: 20px;
    line-height: 20px;
    display: flex;
    justify-content: flex-end;
  }
  .btn-txt {
    font-size: 14px;
    color: @blue;
    padding: 0 5px;
  }
  .tabsWrap {
    height: 50px;
  }
  .sTradingviewView {
    height: calc(100%);
    border-radius: 8px;
    margin-bottom: 30px;
    &.fullscreen {
      height: 100%;
    }
  }
}
.box-shadow {
  border-bottom-right-radius: 10px;
  border-bottom-left-radius: 10px;
  box-shadow: 0px 4px 3px rgba(0, 0, 0, 0.08);
}
.trangle {
  position: absolute;
  right: 0;
  bottom: 0;
}
.more-icon {
  position: absolute;
  right: 0;
  bottom: 0;
}
.lh-20 {
  line-height: 20px;
}
.header-bg {
  background-color: rgb(19, 31, 48);
}
.quote-key-text {
  color: #6d87a8;
}
.quote-key-text:hover {
  color: #1987ed;
}
.quote-value-text {
  color: @blue;
}
.item-border {
  // eslint-disable-next-line prettier/prettier
  border-bottom: 2.5px solid @blue;
}
#k-linebox/deep/.el-loading-mask {
  z-index: 10 !important;
}
</style>
